#! /usr/bin/env python
# -*- coding: utf-8 -*-

import os
import json
import re
import time

import FileHostProtoType


class rsitem(FileHostProtoType.HostItem):
    def __init__(self, name, type, code, link='', encrypt_name='', server_name=''):
        FileHostProtoType.HostItem.__init__(self, name, type, code, link, encrypt_name, server_name)
        self.parent_id = 0
    
class rapidshare(FileHostProtoType.FileHostProcess):            
    def __init__(self, user, pwd):
        FileHostProtoType.FileHostProcess.__init__(self)
        self.hostname = "RapidShare" 
        self._opener = None
        self._user = user
        self._pwd = pwd
        self.islogin = False
        self.logtype = 'poster'
        self.apikey = ''
        self._cid = 1
        self.cookie = ''
        
    @property
    def cid(self):
        self._cid += 1
        return self._cid
    
    def login(self):
        if self.islogin:
            return True
        #build opener
        self.generateOpener()
        self.fherr.write('login to RapidShare %s/%s...'%(self._user,'*'*len(self._pwd)))
        loginData = {}
        login_url = "http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=getaccountdetails&login={0}&password={1}&withcookie=1&cbid={2}"\
                    .format(self._user,self._pwd, self.cid)
        response = self.loginFileHost(login_url, loginData)
#        print response
        if 'ERROR' in response:
            self.fherr.write("User %s Failed to Login RapidShare." % self._user)
            return False
        s_pos = response.find("cookie=")
        e_pos = response.find('\n', s_pos)
        self.cookie = response[s_pos+7:e_pos]
        if not self.cookie:
            self.fherr.write("Failed to get cookie.")
            self.fherr.write("User %s Failed to Login RapidShare." % self._user)
            return False
        self.fherr.write("User %s logined." % self._user)
        self.islogin = True
        return True
    
    def getFolderList(self):
        folderlist = []
        url = "http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=listrealfolders&cookie=%s&cbid=%s" % (self.cookie,self.cid)
        folder_page = self.post_request(url)
        tokens = folder_page.splitlines()
        for t in tokens:
            ttokens = t.split(',')
            if len(ttokens) < 3:
                continue
            id = ttokens[0]
            pid = ttokens[1]
            name = ttokens[2].replace('%2C',',')
            folder_item = rsitem(name,'folder', id, '')
            folder_item.parent_id = pid
            folderlist.append(folder_item)
            # self.fherr.write("%s, %s, %s" % (name, id ,pid ))
        for folder in folderlist:
            folder.type = self.get_full_folderpath(folder, folderlist) 
            # self.fherr.write(folder.type)
        return folderlist            
    
    def get_full_folderpath(self, folder, folderlist):
        dirs = []
        dirs.insert(0, folder.name)
        # self.fherr.write("find fullpath for :%s, %s, %s" % (folder.name, folder.id ,folder.parent_id ))
        pid = folder.parent_id
        while pid != "0":
            old_pid = pid
            for f in folderlist:
                if f.id == pid:
                    dirs.insert(0, f.name)
                    pid = f.parent_id
                    break
            if pid == old_pid:
                self.fherr.write("failed to find parent folder for (%s, %s, %s)" % (folder.name, folder.id ,folder.parent_id ))
                break
#        print dirs
        return '/'.join(dirs)
                     
           
    def getFileList(self):
        return []
    
    def pre_process_folderpath(self, newfolder):
        '''
        input: folder_a/folder_b/folder_c
        output: ["folder_a", 
                 "folder_a/folder_b", 
                 "folder_a/folder_b/folder_c"]
        '''
        foldertree = []
        
        if re.compile("^[a-zA-z0-9-_]+$").match(newfolder.replace('/','')) == None:
            self.fherr.write("The Folder must be more than 2 symbols long and must consist only of A-Z,0-9,- and _")
            return foldertree
        if newfolder[0] == '/':
            newfolder = newfolder[1:]
        if newfolder[-1] == '/':
            newfolder = newfolder[:-1]
        dirs = newfolder.split('/')        
        foldertree = ['/'.join(dirs[:i+1]) for i in range(len(dirs))]
        
        return dirs, foldertree

    def createFolder(self, newfolder):
        dirs, foldertree = self.pre_process_folderpath(newfolder)            
        remoteFolders = self.getFolderList()

        remoteFolderNames = [f.type for f in remoteFolders]
        index = 0
        for i in range(len(foldertree)):
            index = i
            if foldertree[i] in remoteFolderNames:                
                self.fherr.write('Folder %s exists.' % foldertree[i])
                if index == len(foldertree) - 1:
                    folder_item = remoteFolders[remoteFolderNames.index(foldertree[index])]
                    return folder_item
                continue
            else:                
                if i == 0:
                    parentFolder = None
                else:
                    parentFolder = remoteFolders[remoteFolderNames.index(foldertree[i-1])]
                break
        justCreated = None
        for i in range(index,len(foldertree)):
            self.fherr.write("Creating...%s" % foldertree[i])
            justCreated = self.__newFolder(dirs[i], parentFolder)
            if justCreated is None:
                self.fherr.write('Fail to create folder %s' % foldertree[i])
                return None
            parentFolder = justCreated
        justCreated.type = foldertree[-1]
        return justCreated

    def __newFolder(self, newfolder, parentfolder=None):
        pid = '0'
        if parentfolder is not None:
            pid = parentfolder.id
        url = "http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=addrealfolder&cookie=%s&parent=%s&name=%s&cbid=%s" \
                % (self.cookie, pid, newfolder, self.cid)
        response = self.post_request(url)        
        newCreated = None
        if response.isdigit():
            folder_id = response
            newCreated = rsitem(newfolder, 'folder', folder_id, '')
            newCreated.parent_id = pid
        return newCreated
    
    def moveto(self, items, destFolder):
        '''
        move a few file to a destinate folder
        '''
        file_ids = ','.join([item.id for item in items]) 
        if not file_ids:
            self.fherr.write("no file to move.")
            return           
        url = "http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=movefilestorealfolder&cookie=%s&realfolder=%s&files=%s&cbid=%s" \
                % (self.cookie, destFolder.id, file_ids, self.cid)
        
        response = self.post_request(url)
        if response == "OK":
            self.fherr.write("Success to move files")
        else:
            self.fherr.write("It seems something wrong when moving file.")
            self.fherr.write(response)
    
    def upload_web(self, file, progressLog=None, other_args=None, send_range=None):
        #indexpage        
        server_num_api = 'http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=nextuploadserver'
        server_num = self.post_request(server_num_api)
          
        upload_url = "http://rs%s.rapidshare.com/cgi-bin/rsapi.cgi" % server_num        
        
        info = "Uploading...%s" % file
        filesize = os.path.getsize(file)
        filename = self.rename_func(file)
        start_point = 0
        if send_range is not None:
            #range is a 3-tuple, <start, end, number>
            filesize = send_range[1] - send_range[0] + 1
            filename += ".%03d" % send_range[2]
            start_point = send_range[0]
            info += " part%d" % send_range[2]
            
        fileobj = open(file, 'rb')
        fileobj.seek(start_point)  
        
        data = {"sub":"upload",
                "login":self._user,
                "password":self._pwd,
                "filecontent":fileobj}
        
        self.fherr.write(info)
        
        callback = None
        if progressLog is not None:
            callback = progressLog.write
        result = self.post_request(upload_url, \
                                   data, \
                                   cb=callback, \
                                   retry=1, \
                                   setfilename=filename, \
                                   setfilesize=filesize)
        #result
#        print result
        if result is None:
            self.fherr.write("Error when uploading. Retry later.")
            return
        
        if 'COMPLETE' in result:
            tokens = result[9:].split(',')
#            print tokens
            id = tokens[0]
            filename = tokens[1]
            size = int(tokens[2])
            md5 = tokens[3]
            
            if not size == filesize:
                self.fherr.write("ORZ, Server return a wrong filesize, even though uploading completed.")
                return
            link = "http://rapidshare.com/files/{}/{}".format(id, filename)
            item = rsitem(os.path.basename(file), 'file', id, link, filename)
            self.newupload.append(item)
            self.fhout.write(item.format()) 
            return item
    
        if 'ERROR' in result:
            self.fherr.write("Get a wrong result after uploaded.")
            self.fherr.write(result)
            return